package com.windward.vii.service.weixin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.jersey.api.client.ClientResponse;
import com.windward.vii.common.JsonResult;
import com.windward.vii.common.ResultCode;
import com.windward.vii.config.WeixinPayConfig;
import com.windward.vii.service.weixin.bean.WeixinAccessToken;
import com.windward.vii.service.weixin.bean.WeixinUserInfo;
import com.windward.vii.utils.HttpRestClient;
import com.windward.vii.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317853&token=&lang=zh_CN
 */
@Component
public class WeixinAuthService {

    private static final Logger logger = LoggerFactory.getLogger(WeixinAuthService.class);

    // 通过code获取access_token
    // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";

    // 刷新或续期access_token使用
    // https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
    private static final String REFRESH_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    // 检验授权凭证（access_token）是否有效
    // https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID
    private static final String CHECK_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/auth";

    // 获取用户个人信息
    // https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    private static final String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo";

    @Resource
    WeixinPayConfig weixinPayConfig;


    /**
     * 通过code获取access_token
     */
    public JsonResult getAccessToken(String code) {
        if(StringUtils.isBlank(code)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的code");
        }
        StringBuilder url = new StringBuilder();
        url.append(GET_ACCESS_TOKEN_URL).append("?appid=").append(weixinPayConfig.getAppid())
                .append("&secret=").append(weixinPayConfig.getApiKey())
                .append("&code=").append(code)
                .append("&grant_type=authorization_code");
        ClientResponse response = HttpRestClient.get(url.toString());
        if(response == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取access_token失败(response err)，请重试");
        }
        String content = response.getEntity(String.class);
        if(StringUtils.isBlank(content)) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取access_token失败(content err)，请重试");
        }
        logger.info("getAccessToken-response={}" + content);
        JSONObject jsonObject = JSON.parseObject(content);
        if(jsonObject == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取access_token失败(jsonObject err)，请重试");
        }
        JsonResult result = new JsonResult();
        if(jsonObject.containsKey("errcode")) {
            result.setCode(jsonObject.getInteger("errcode"));
            result.setMsg(jsonObject.getString("errmsg"));
        } else {
            result.setCode(ResultCode.SUCCESS_CODE);
            result.setMsg(ResultCode.SUCCESS_MSG);
            result.setBody(JSON.parseObject(content, WeixinAccessToken.class));
        }
        return result;
    }

    /**
     * 刷新或续期access_token使用
     */
    public JsonResult refreshAccessToken(String refresh_token) {
        if(StringUtils.isBlank(refresh_token)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的refresh_token");
        }
        StringBuilder url = new StringBuilder();
        url.append(REFRESH_ACCESS_TOKEN_URL).append("?appid=").append(weixinPayConfig.getAppid())
                .append("&grant_type=refresh_token")
                .append("&refresh_token=").append(refresh_token);
        ClientResponse response = HttpRestClient.get(url.toString());
        if(response == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "refresh_token失败(response err)，请重试");
        }
        String content = response.getEntity(String.class);
        if(StringUtils.isBlank(content)) {
            return new JsonResult(ResultCode.ERROR_CODE, "refresh_token失败(content err)，请重试");
        }
        logger.info("getAccessToken-response={}" + content);
        JSONObject jsonObject = JSON.parseObject(content);
        if(jsonObject == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "refresh_token失败(json err)，请重试");
        }
        JsonResult result = new JsonResult();
        if(jsonObject.containsKey("errcode")) {
            result.setCode(jsonObject.getInteger("errcode"));
            result.setMsg(jsonObject.getString("errmsg"));
        } else {
            result.setCode(ResultCode.SUCCESS_CODE);
            result.setMsg(ResultCode.SUCCESS_MSG);
            result.setBody(JSON.parseObject(content, WeixinAccessToken.class));
        }
        return result;
    }

    /**
     * 检验授权凭证（access_token）是否有效
     */
    public JsonResult checkAccessToken(String access_token, String openid) {
        if(StringUtils.isBlank(access_token)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的refresh_token");
        }
        if(StringUtils.isBlank(openid)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的openid");
        }
        StringBuilder url = new StringBuilder();
        url.append(CHECK_ACCESS_TOKEN_URL)
                .append("&access_token=").append(access_token)
                .append("&openid=").append(openid);
        ClientResponse response = HttpRestClient.get(url.toString());
        if(response == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "检验授权凭证失败(response err)，请重试");
        }
        String content = response.getEntity(String.class);
        if(StringUtils.isBlank(content)) {
            return new JsonResult(ResultCode.ERROR_CODE, "检验授权凭证失败(content err)，请重试");
        }
        logger.info("checkAccessToken-response={}" + content);
        JSONObject jsonObject = JSON.parseObject(content);
        if(jsonObject == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "检验授权凭证失败(json err)，请重试");
        }
        JsonResult result = new JsonResult();
        int errcode = jsonObject.getInteger("errcode");
        if(errcode != 0) {
            result.setCode(jsonObject.getInteger("errcode"));
            result.setMsg(jsonObject.getString("errmsg"));
        } else {
            result.setCode(ResultCode.SUCCESS_CODE);
            result.setMsg(jsonObject.getString("errmsg"));
        }
        return result;
    }

    /**
     * 获取用户个人信息
     * @param access_token
     * @param openid
     * @return
     */
    public JsonResult getUserInfo(String access_token, String openid) {
        if(StringUtils.isBlank(access_token)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的access_token");
        }
        if(StringUtils.isBlank(openid)) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "无效的openid");
        }
        StringBuilder url = new StringBuilder();
        url.append(USER_INFO_URL).append("?access_token=").append(access_token)
                .append("&openid=").append(openid);
        ClientResponse response = HttpRestClient.get(url.toString());
        if(response == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取用户信息失败(response err)，请重试");
        }
        String content = response.getEntity(String.class);
        if(StringUtils.isBlank(content)) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取用户信息失败(content err)，请重试");
        }
        logger.info("getUserInfo-response={}" + content);
        JSONObject jsonObject = JSON.parseObject(content);
        if(jsonObject == null) {
            return new JsonResult(ResultCode.ERROR_CODE, "获取用户信息失败(json err)，请重试");
        }
        JsonResult result = new JsonResult();
        if(jsonObject.containsKey("errcode")) {
            result.setCode(jsonObject.getInteger("errcode"));
            result.setMsg(jsonObject.getString("errmsg"));
        } else {
            result.setCode(ResultCode.SUCCESS_CODE);
            result.setMsg(ResultCode.SUCCESS_MSG);
            result.setBody(JSON.parseObject(content, WeixinUserInfo.class));
        }
        return result;
    }

}
